iT邦幫忙

2024 iThome 鐵人賽

DAY 20
2
Kubernetes

都什麼年代了,還在學 Kubernetes系列 第 20

學 Kubernetes 的第二十天 - Pod - Init Container

  • 分享至 

  • xImage
  •  

在現代軟體開發和部署的複雜生態中,服務的準備和初始化往往需要一系列精心編排的步驟。從環境配置到依賴服務的啟動,每一個階段都是確保應用順利運行的關鍵。Kubernetes深諳這一挑戰,並提供了一個優雅的解決方案:Init Container。

Init Container 是什麼?

Init Container (Init 容器) 是 Kubernetes 中的一種特別設計,它的任務是在應用容器啟動之前完成初始化工作。這些 Init Container 可以負責一系列準備工作,例如配置環境變數、檢查依賴服務是否已啟動等。每個 Init Container 都必須成功完成後,Kubernetes 才會啟動下一個 Init Container 或最終的應用容器。這種機制確保了應用可以在一個準備妥當的環境中穩定運行。

https://ithelp.ithome.com.tw/upload/images/20241004/20168212RdBSisxmvJ.png

Init Container 與普通容器的不同之處

Init Container 雖然與普通容器非常相似,但有以下兩個重要的區別:

  • 成功運行至完成:Init 容器必須成功完成其任務後才能退出,並繼續執行下一個容器或應用容器。
  • 按順序運行:每個 Init 容器必須在前一個容器成功完成後才會啟動,這確保了初始化步驟的順序執行。

即使 Init 容器會不斷重試,但如果 Pod 的 restartPolicy 被設置為 "Never",當 Init 容器失敗時,Pod 狀態會被標記為失敗。  

此外,Init 容器支援應用容器的所有功能,包括資源限制、資料卷掛載和安全配置。不過,Init 容器對資源請求和限制的處理方式略有不同,詳細說明請參見 Init 容器與 Pod 資源請求和限制的處理

Init 容器的設計目的是快速完成初始化任務並退出,而應用容器負責持續運行應用程式,因此 Probelifecycle 配置不適用於 Init 容器。

如果一個 Pod 定義了多個 Init 容器,這些容器會按順序執行,且只有當前的 Init 容器成功運行後,下一個 Init 容器才會啟動。所有的 Init 容器都運行完成後,Kubernetes 才會初始化 Pod 並啟動應用容器。

Init 容器能做什麼

Init 容器有獨立的映像檔,並能使用與應用容器分離的啟動程式碼,這帶來了許多優勢:

  • 專用工具支持:你可以在 Init 容器中使用一些應用容器中沒有的工具(如 sedawk 等),這避免了為應用容器增加不必要的工具或擴大映像檔大小。
  • 分離開發工作:應用容器和 Init 容器可以由不同的團隊負責開發,降低了彼此之間的耦合。
  • 不同的檔案系統檢視:Init 容器可以訪問應用容器無法訪問的資源,如 Secret。
  • 延遲應用啟動:Init 容器可以在初始化完成前阻止應用容器啟動,確保應用容器運行時已準備好所需的資源。
  • 安全性增強:透過 Init 容器處理初始化任務,應用容器的權限需求可以降到最低,從而增強整體系統的安全性。

簡單來說,Init 容器讓應用和初始化邏輯分離,應用容器可以專注於最核心的應用邏輯,並以最少的權限運行。

Init 容器與 Pod 資源請求和限制的處理

Init 容器也可以定義資源請求和限制,不過它的處理方式與應用容器有所不同。以下是一個示例:

  • Init 容器 init1 請求 100m CPU,限制 200m CPU。
  • Init 容器 init2 請求 150m CPU,限制 250m CPU。
  • 應用容器 app1 請求 300m CPU,限制 500m CPU。
  • 應用容器 app2 請求 200m CPU,限制 300m CPU。

資源計算的邏輯如下:

  • Init 容器的最大資源請求:150m(來自 init2 的請求)。
  • Init 容器的最大資源限制:250m(來自 init2 的限制)。
  • 應用容器的總資源請求:500m(來自 app1app2 的請求總和)。
  • 應用容器的總資源限制:800m(來自 app1app2 的限制總和)。

因此,Pod 的有效資源計算如下:

  • 請求總和:500m(應用容器的請求總和大於 Init 容器的請求最大值)。
  • 限制總和:800m(應用容器的限制總和大於 Init 容器的限制最大值)。

這種資源計算方式確保了 Init 容器能夠獲取足夠的資源來執行初始化任務,而應用容器則能在資源充足的情況下穩定運行。

實作

組態檔案: pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app.kubernetes.io/name: MyApp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

上述的組態檔案定義了一個具有 2 個 Init 容器的簡單 Pod。 第一個等待 myservice 啟動, 第二個等待 mydb 啟動。 一旦這兩個 Init 容器都啟動完成,Pod 將啟動應用容器。

  • 建立 Pod
kubectl apply -f pod.yaml
  • 檢查 Pod 狀態
kubectl get pod myapp-pod
---
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          55s
  • 檢查 Pod 詳細狀態
kubectl describe pod myapp-pod

結果如下

Name:             myapp-pod
Namespace:        default
[...]
Labels:           app.kubernetes.io/name=MyApp
Status:           Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:          Running
[...]
  init-mydb:
[...]
    State:          Waiting
      Reason:       PodInitializing
      Ready:          False
[...]
Containers:
  myapp-container:
[...]
    State:          Waiting
      Reason:       PodInitializing
    Ready:          False
[...]
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  3m19s  default-scheduler  Successfully assigned default/myapp-pod to wslkind-worker2
  Normal  Pulled     3m19s  kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    3m19s  kubelet            Created container init-myservice
  Normal  Started    3m19s  kubelet            Started container init-myservice

可以看到,目前的 Pod 的應用容器狀態都是 Waiting,Init 容器將會等到發現名稱為 mydbmyservice 的服務後,才會完成並關閉容器。

現在我們來建立 mydbmyservice 服務。

組態檔案: service.yaml

---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377
  • 建立服務
kubectl apply -f service.yaml
  • 重新檢查 Pod 狀態
kubectl get pods myapp-pod
---
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/1     Running   0          9m23s
  • 檢查 Pod 詳細狀態
kubectl describe pod myapp-pod

結果如下

[...]
Events:
  Type    Reason     Age    From               Message
  ----    ------     ----   ----               -------
  Normal  Scheduled  9m44s  default-scheduler  Successfully assigned default/myapp-pod to wslkind-worker2
  Normal  Pulled     9m44s  kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    9m44s  kubelet            Created container init-myservice
  Normal  Started    9m44s  kubelet            Started container init-myservice
  Normal  Pulled     27s    kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    27s    kubelet            Created container init-mydb
  Normal  Started    27s    kubelet            Started container init-mydb
  Normal  Pulled     26s    kubelet            Container image "busybox:1.28" already present on machine
  Normal  Created    26s    kubelet            Created container myapp-container
  Normal  Started    26s    kubelet            Started container myapp-container

可以看到,建立 mydbmyservice 服務後,init-myservice 容器便完成,緊接著啟動並執行 init-mydb 容器,等待它也完成後,接著應用容器 myapp-container 便開始運作。

小結

Init Container 透過多容器 Pod 的特性,不僅解決了傳統容器化應用中的初始化難題,還為開發者提供了更大的靈活性和控制力。通過將初始化邏輯與主應用邏輯分離,Init Container 促進了更清晰的責任劃分和更高的系統可靠性。

在實際部署中,Init Container 的應用範圍廣泛,從簡單的環境檢查到複雜的數據預處理都可以輕鬆實現。它的存在使得容器化應用的生命週期管理更加精細和可控,為構建健壯、可擴展的雲原生應用奠定了堅實基礎。


參考


上一篇
學 Kubernetes 的第十九天 - Workloads - Job & CronJob
下一篇
學 Kubernetes 的第二十一天 - Pod - Probe
系列文
都什麼年代了,還在學 Kubernetes37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言